﻿using Hx.ADSyncPlatform.ActiveDirectory.Access;
using Hx.ADSyncPlatform.ActiveDirectory.Extension;
using Hx.ADSyncPlatform.ActiveDirectory.Model;
using Hx.ADSyncPlatform.ActiveDirectory.Service.Base;
using System.Collections.Generic;
using System.DirectoryServices;
using ADONotFoundException = System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException;

namespace Hx.ADSyncPlatform.ActiveDirectory.Service
{
    /// <summary>
    /// 域控
    /// </summary>
    public class DomainControllerService : BaseService
    {

        private ADConnection ADCInfo;
        public DomainControllerService(ADConnection _adcInfo)
        {
            this.ADCInfo = _adcInfo;
        }
        //hack：这个Search没有任何用途
        /// <summary>
        ///自定义查询
        /// </summary>
        /// <param name="filter">LDAP查询语句</param>
        /// <param name="propertiesToLoad">需要返回的属性</param>
        /// <param name="searchScope">查询层级</param>
        /// <param name="pagination">分页信息，NULL时返回所有</param>
        /// <returns>返回域控集合</returns>
        //public PaginationData<DomainController> Search(string filter, List<string> propertiesToLoad, SearchScopeDerivation searchScope, Pagination pagination)
        //{
        //    using (var adc = new ADConnection(ADCInfo.LDAPPath, ADCInfo.UserName, ADCInfo.Password))
        //    {
        //        var dcs = new DomainControllerAccess(adc.RootEntry).Search(filter, propertiesToLoad, searchScope.Convert(), pagination);
        //        if (dcs != null && dcs.Count > 0)
        //        {
        //            List<DomainController> data = new List<DomainController>();
        //            #region 分页参数
        //            int startIndex = 0;
        //            int enIndex = dcs.Count;
        //            int count = dcs.Count;
        //            if (pagination != null && pagination.PageIndex != 0 && pagination.PageSize != 0)
        //            {
        //                startIndex = (pagination.PageIndex - 1) * pagination.PageSize;
        //                if (pagination.PageSize < (count - startIndex))
        //                    enIndex = startIndex + pagination.PageSize;
        //                else if (pagination.PageSize > (count - startIndex))
        //                    enIndex = count;
        //            }
        //            #endregion
        //            for (int i = startIndex; i < enIndex; i++)
        //            {
        //                var item = dcs[i]?.Properties?.ConvertTo<DomainController>();
        //                if (item != null)
        //                {
        //                    data.Add(item);
        //                } 
        //            }
        //            return new PaginationData<DomainController>()
        //            {
        //                Data = data,
        //                Pagination = pagination,
        //                TotalItems = count
        //            };
        //        }
        //        return null;
        //    }
        //}

        /// <summary>
        /// 查询组织下的域控
        /// </summary>
        /// <param name="orgCn">组织CN</param>
        /// <param name="searchScope">查询层级</param>
        /// <param name="searchLocation">查询位置</param>
        /// <returns>域控集合</returns>
        public List<DomainController> Get(string orgCn, SearchScopeDerivation searchScope)
        {
            using (var adc = new ADConnection(ADCInfo.LDAPPath, ADCInfo.UserName, ADCInfo.Password))
            {
                DirectoryEntry org = null;
                //hack：new xxxx(【xx.RootEntry】)这种写法感觉很怪异
                var orgDe = new OrganizationAccess().Single(adc.RootEntry, orgCn);
                if (orgDe == null)
                {
                    //hack:此处用NullReferenceException这个异常不合适，可以考虑如下：
                    /*
                     * System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectExistsException 类异常引发时创建 Active Directory 域服务对象以及该对象已存在于基础目录存储区。
                     * System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException 类异常在基础目录存储区中找不到请求的对象时引发。
                     * 还有一些.NET提供的异常，都可以参考。
                     */
                    throw new ADONotFoundException($"组织【{orgCn}】不存在，查询无法继续。");
                }

                org = orgDe.GetDirectoryEntry();
                var computerDes = new DomainControllerAccess().Get(org, searchScope.Convert());
                List<DomainController> data = new List<DomainController>();
                if (computerDes == null || computerDes.Count == 0)
                {
                    return data;
                }

                foreach (SearchResult computerDe in computerDes)
                {
                    var item = computerDe?.Properties?.ConvertTo<DomainController>();
                    if (item != null)
                    {
                        data.Add(item);
                    }
                }
                return data;
            }
        }
    }
}
